/*!
 * schedule - controllers/schedule.js
 */

/**
 * Module dependencies.
 */

var util = require('util');
var validator = require('validator');
var logger = require('../common/loggerUtil').getLogger('schedule');
var at = require('../common/at');
var User = require('../proxy').User;
var Schedule = require('../proxy/schedule');
var EventProxy = require('eventproxy');
var tools = require('../common/tools');
var store = require('../common/store');
var config = require('../config');
var _ = require('lodash');
var cron_array = require('../common/cron_array');
var Q = require('q');

/**
 * list schedules
 * @param  {[type]}   req  [description]
 * @param  {[type]}   res  [description]
 * @param  {Function} next [description]
 * @return {[type]}        [description]
 */
exports.index = function(req, res, next) {
    var METHOD = 'index';
    // #TODO add permissions control

    var limit = config.list_topic_count;
    var query = {};
    var page = parseInt(req.query.page, 10) || 1;
    page = page > 0 ? page : 1;

    var options = {
        skip: (page - 1) * limit,
        limit: limit,
        sort: '-top -last_reply_at'
    };
    var optionsStr = JSON.stringify(query) + JSON.stringify(options);

    var ep = EventProxy.create('topics', 'pages', function(topics, pages) {
        res.render('schedule/index', {
            topics: topics,
            current_page: page,
            list_topic_count: limit,
            tops: [],
            no_reply_topics: [],
            pages: pages,
            tabs: config.tabs,
            tab: 'schedules',
            pageTitle: '规划任务'
        });
    });

    Schedule.getSchedulesByQuery(query, options)
        .then(function(result) {
            logger.debug(METHOD, 'Get result ' + JSON.stringify(result));
            ep.emit('topics', result);
        })
        .fail(function(err) {
            ep.emit('error', err);
        });

    Schedule.getCountByQuery(query, ep.done(function(all_topics_count) {
        ep.emit('pages', Math.ceil(all_topics_count / limit));
    }));

    ep.fail(next);
}

/**
 * Display a schedule
 *
 * @param  {HttpRequest} req
 * @param  {HttpResponse} res
 * @param  {Function} next
 */
exports.detail = function(req, res, next) {
    var METHOD = 'detail';

    function isUped(user, reply) {
        if (!reply.ups) {
            return false;
        }
        return reply.ups.indexOf(user._id) !== -1;
    }

    var _id = req.params.sid;
    if (_id.length !== 24) {
        return res.render('notify/notify', {
            error: '此记录不存在或已被删除。'
        });
    }

    var events = ['schedule'];
    var ep = EventProxy.create(events, function(schedule) {
        res.render('schedule/detail', {
            // to make it Compatible with
            // the old topic/index.html
            // resolve some properties
            topic: _.merge(schedule, {
                title: schedule.name,
                friendly_create_at: schedule.create_date.toFormat("YYYY-MM-DD HH24:MI:SS"),
                friendly_update_at: schedule.update_date.toFormat("YYYY-MM-DD HH24:MI:SS"),
                // #TODO resolve the user markers like proxy/topic.js
                // at.linkUsers(topic.content, proxy.done('topic', function(str) {
                //      topic.linkedContent = str;
                //      return topic;
                // }));
                linkedContent: schedule.description
            }),
            isUped: isUped,
            author_other_topics: []
        });
    });

    ep.fail(next);

    Schedule.getScheduleById(_id)
        .then(function(result) {
            logger.debug(METHOD, 'get schedule ' + JSON.stringify(result));
            ep.emit('schedule', result);
        })
        .fail(function(err) {
            ep.emit('error', err);
        });
};

exports.create = function(req, res, next) {
    res.render('schedule/edit', {
        tabs: config.tabs,
        eam_maintain_toolkits: [],
        eam_maintain_parts: []
    });
};


/**
 * need to convert weekday to range 0~6, but cronjs in front side
 * use 1~7 as weekdays.
 */
function _fixWeekdayRange(weekdays) {
    var result = [];
    weekdays.forEach(function(w) {
        if (w == '7') {
            result.push('0');
        } else {
            result.push(w);
        }
    })
    return _.uniq(result);
}

/**
 * need to convert month to range 0~11, but cronjs in front side
 * use 1~12 as months.
 */
function _fixMonthRange(months) {
    var result = [];
    months.forEach(function(m) {
        if (m == '12') {
            result.push('0');
        } else {
            result.push(m);
        }
    })
    return _.uniq(result);
}

/**
 * Create new schedule by post
 */
exports.put = function(req, res, next) {
    var METHOD = 'put';
    logger.debug(METHOD, 'request body ' + JSON.stringify(req.body));

    // resolve parameters in body
    var category = validator.trim(req.body.tab),
        name = validator.trim(req.body.schedule_name),
        description = validator.trim(req.body.schedule_description),
        time_settings_object = {
            minute: req.body.minute,
            hour: req.body.hour,
            day: req.body.day,
            month: _fixMonthRange(req.body.month),
            weekday: _fixWeekdayRange(req.body.weekday)
        },
        time_settings;

    // valiate parameters
    var editError;
    try {
        time_settings = cron_array.arrayToPattern(time_settings_object);
    } catch (err) {
        editError = '时间设置错误！'
    }

    if (editError) {
        res.status(422);
        return res.render('schedule/edit', {
            edit_error: '时间设置错误',
            tab: category,
            tabs: config.tabs,
            schedule_name: name,
            schedule_description: description,
            schedule_time_settings: time_settings_object
        });
    }
    // end validate

    Schedule.newAndSave(category, name, time_settings,
            req.session.user._id, null, description)
        .then(function(result) {
            res.redirect(util.format('/modules/schedule/%s', result._id));
        })
        .fail(function(err) {
            logger.error('put', err);
            res.render('notify/notify', {
                error: '服务异常，稍后再试。'
            });
        });

};

exports.showEdit = function(req, res, next) {
    var METHOD = "showEdit";
    var _id = req.params.sid;

    Schedule.getScheduleById(_id)
        .then(function(result) {
            logger.debug(METHOD, 'Get result ' + JSON.stringify(result));
            if (String(result.author._id) === String(req.session.user._id) || req.session.user.is_admin) {
                res.render('schedule/edit', {
                    action: 'edit',
                    topic_id: result._id,
                    tab: result.category,
                    tabs: config.tabs,
                    schedule_name: result.name,
                    schedule_description: result.description,
                    // #TODO convert time settings into array.
                    schedule_time_settings: cron_array.patternToArray(result.time_settings)
                });
            } else {
                res.render('notify/notify', {
                    error: '对不起，你不能编辑此话题。'
                });
            }
        })
        .fail(function(err) {
            logger.error(METHOD, err);
            res.render('notify/notify', {
                error: '此纪录不存在或已被删除'
            });
        });
};

exports.update = function(req, res, next) {
    var METHOD = 'update';
    var _id = req.params.sid;
    var name = req.body.schedule_name,
        description = req.body.schedule_description,
        time_settings_object = {
            minute: req.body.minute,
            hour: req.body.hour,
            day: req.body.day,
            month: _fixMonthRange(req.body.month),
            weekday: _fixWeekdayRange(req.body.weekday)
        },
        // resolve value from database
        category;

    Schedule.getScheduleById(_id)
        .then(function(result) {
            if (result.author._id.equals(req.session.user._id) || req.session.user.is_admin) {
                category = result.category;
                // 验证
                var editError;
                var time_settings;
                if (_.some([name], function(parm) {
                        return typeof parm === 'undefined' || parm === null || parm == '';
                    })) {
                    editError = '缺少参数或参数值错误';
                }

                try {
                    time_settings = cron_array.arrayToPattern(time_settings_object);
                } catch (err) {
                    editError = '时间设置错误';
                }
                // END 验证

                if (editError) {
                    throw {
                        message: editError,
                        code: 2
                    };
                }

                // no error, everything seems fine, save the item
                //保存话题
                result.update_at = new Date();
                result.name = name;
                result.description = description;
                result.time_settings = time_settings;

                result.save(function(err) {
                    if (err) {
                        return next(err);
                    }
                    // #TODO 支持发送at消息
                    // at.sendMessageToMentionUsers(result.category + " " + result.schedule_id + " 已经更新。", topic._id, req.session.user._id);

                    res.redirect('/modules/schedule/' + result._id);
                });
            } else {
                throw {
                    message: '对不起，你不能编辑此话题。',
                    code: 1
                };
            }
        })
        .fail(function(err) {
            logger.error(METHOD, JSON.stringify(err));
            if (err.code) {
                switch (err.code) {
                    case 1:
                        res.render('notify/notify', {
                            error: err.message
                        });
                        break;
                    case 2:
                        logger.debug('schedule,edit...');
                        res.render('schedule/edit', {
                            edit_error: err.message,
                            action: 'edit',
                            topic_id: _id,
                            tab: category,
                            tabs: config.tabs,
                            schedule_name: name,
                            schedule_description: description,
                            schedule_time_settings: time_settings_object
                        });
                        break;
                    default:
                        break;
                }
            } else {
                res.render('notify/notify', {
                    error: '服务异常，稍后再试。'
                });
            }
        });
};

exports.delete = function(req, res, next) {
    //删除话题, 话题作者topic_count减1
    //删除回复，回复作者reply_count减1
    //删除topic_collect，用户collect_topic_count减1

    var topic_id = req.params.sid;

    Schedule.getScheduleById(topic_id)
        .then(function(topic) {
            if (!req.session.user.is_admin && !(topic.author._id.equals(req.session.user._id))) {
                res.status(403);
                return res.send({
                    success: false,
                    message: '无权限'
                });
            }
            if (!topic) {
                res.status(422);
                return res.send({
                    success: false,
                    message: '此话题不存在或已被删除。'
                });
            }
            topic.remove(function(err) {
                if (err) {
                    return res.send({
                        success: false,
                        message: err.message
                    });
                }
                res.send({
                    success: true,
                    message: '话题已被删除。'
                });
            });
        })
        .fail(function(err) {
            return res.send({
                success: false,
                message: err.message
            });
        });
};

// 设为置顶
exports.top = function(req, res, next) {
    var topic_id = req.params.tid;
    var is_top = req.params.is_top;
    var referer = req.get('referer');
    if (topic_id.length !== 24) {
        res.render('notify/notify', {
            error: '此话题不存在或已被删除。'
        });
        return;
    }
    Topic.getTopic(topic_id, function(err, topic) {
        if (err) {
            return next(err);
        }
        if (!topic) {
            res.render('notify/notify', {
                error: '此话题不存在或已被删除。'
            });
            return;
        }
        topic.top = is_top;
        topic.save(function(err) {
            if (err) {
                return next(err);
            }
            var msg = topic.top ? '此话题已经被置顶。' : '此话题已经被取消置顶。';
            res.render('notify/notify', {
                success: msg,
                referer: referer
            });
        });
    });
};

// 设为精华
exports.good = function(req, res, next) {
    var topicId = req.params.tid;
    var isGood = req.params.is_good;
    var referer = req.get('referer');
    Topic.getTopic(topicId, function(err, topic) {
        if (err) {
            return next(err);
        }
        if (!topic) {
            res.render('notify/notify', {
                error: '此话题不存在或已被删除。'
            });
            return;
        }
        topic.good = isGood;
        topic.save(function(err) {
            if (err) {
                return next(err);
            }
            var msg = topic.good ? '此话题已加精。' : '此话题已经取消加精。';
            res.render('notify/notify', {
                success: msg,
                referer: referer
            });
        });
    });
};

exports.collect = function(req, res, next) {
    var topic_id = req.body.topic_id;
    Topic.getTopic(topic_id, function(err, topic) {
        if (err) {
            return next(err);
        }
        if (!topic) {
            res.json({
                status: 'failed'
            });
        }

        TopicCollect.getTopicCollect(req.session.user._id, topic._id, function(err, doc) {
            if (err) {
                return next(err);
            }
            if (doc) {
                res.json({
                    status: 'success'
                });
                return;
            }

            TopicCollect.newAndSave(req.session.user._id, topic._id, function(err) {
                if (err) {
                    return next(err);
                }
                res.json({
                    status: 'success'
                });
            });
            User.getUserById(req.session.user._id, function(err, user) {
                if (err) {
                    return next(err);
                }
                user.collect_topic_count += 1;
                user.save();
            });

            req.session.user.collect_topic_count += 1;
            topic.collect_count += 1;
            topic.save();
        });
    });
};

exports.de_collect = function(req, res, next) {
    var topic_id = req.body.topic_id;
    Topic.getTopic(topic_id, function(err, topic) {
        if (err) {
            return next(err);
        }
        if (!topic) {
            res.json({
                status: 'failed'
            });
        }
        TopicCollect.remove(req.session.user._id, topic._id, function(err) {
            if (err) {
                return next(err);
            }
            res.json({
                status: 'success'
            });
        });

        User.getUserById(req.session.user._id, function(err, user) {
            if (err) {
                return next(err);
            }
            user.collect_topic_count -= 1;
            user.save();
        });

        topic.collect_count -= 1;
        topic.save();

        req.session.user.collect_topic_count -= 1;
    });
};

exports.upload = function(req, res, next) {
    req.busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
        store.upload(file, {
            filename: filename
        }, function(err, result) {
            if (err) {
                return next(err);
            }
            res.json({
                success: true,
                url: result.url,
            });
        });
    });

    req.pipe(req.busboy);
};
